package com.zbkj.admin.scheduled;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Lists;
import com.mybatisflex.core.query.QueryWrapper;
import com.zbkj.admin.mapper1.EbOrderProductVoucherRecordMapper;
import com.zbkj.admin.model.order.Order;
import com.zbkj.admin.model.order.OrderDetail;
import com.zbkj.admin.model.product.Product;
import com.zbkj.admin.pojo.EbDividendRecordEntity;
import com.zbkj.admin.pojo.EbShopFlowingWaterEntity;
import com.zbkj.admin.service.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;

/**
 * 店铺流水定时任务
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class ShopScheduled {

    private static final Integer SPLIT_SIZE = 300;

    private final OrderService orderService;
    private final ProductService productService;
    private final OrderDetailService orderDetailService;
    private final EbDividendRecordService dividendRecordService;
    private final EbShopFlowingWaterService shopFlowingWaterService;
    private final EbOrderProductVoucherRecordMapper orderProductVoucherRecordMapper;

    /**
     * 当天营业额一个半小时更新一次
     */
//    @Scheduled(cron = "0 */1 * * * *")
    @Scheduled(cron = "0 30 * * * ? ")
    @Transactional(rollbackFor = Exception.class)
    public void theSameDayTurnover() {
        log.warn("店铺订单流水统计");
        LocalDateTime startTime = LocalDateTime.now();
        Dict data = getOrderPriceList(DateUtil.toLocalDateTime(DateUtil.beginOfDay(DateUtil.date(startTime))), startTime);
        LocalDateTime startDate = data.getBean("startDate"), endDate = data.getBean("startDate"), date = data.getBean("date");
        List<Order> orderList = getOrderList(data);
        orderList.forEach(order -> {
            QueryWrapper where = QueryWrapper.create().from(EbShopFlowingWaterEntity.class).where(EbShopFlowingWaterEntity::getMerId).eq(order.getMerId())
                    .ge(EbShopFlowingWaterEntity::getCreatedTime, startDate).le(EbShopFlowingWaterEntity::getCreatedTime, startDate.plusDays(1)).limit(1);
            // 有流水处理
            if (order.getTotalPrice().longValue() > 0) {
                // 更新当天营业额流水
                EbShopFlowingWaterEntity shopFlowingWater = shopFlowingWaterService.getOne(where);
                if (ObjUtil.isNotEmpty(shopFlowingWater)) {
                    shopFlowingWater.setBusinessLimit(order.getTotalPrice());
                    shopFlowingWaterService.updateById(shopFlowingWater);
                }
            }

        });

    }

    /**
     * 店铺流水统计
     */
//    @Scheduled(cron = "0 0 00 * * ?")
//    @Scheduled(cron = "0 */1 * * * *")
//    @Transactional(rollbackFor = Exception.class)
    public void countShopOrderPrice() {
        log.warn("店铺每天流水统计");
//                QueryWrapper where = QueryWrapper.create().from(EbShopFlowingWaterEntity.class).where(EbShopFlowingWaterEntity::getMerId).eq(order.getMerId())
//                .ge(EbShopFlowingWaterEntity::getCreatedTime, startDate).le(EbShopFlowingWaterEntity::getCreatedTime, endDate);
//        Dict data = getOrderPriceList();
//        LocalDateTime startDate = data.getBean("startDate"), endDate = data.getBean("startDate"), date = data.getBean("date");
//
//        List<Order> orders = getOrderList(data);
//        List<EbShopFlowingWaterEntity> shopFlowingWaterEntities = new ArrayList<>();
//        QueryWrapper where = QueryWrapper.create().from(EbShopFlowingWaterEntity.class).where(EbShopFlowingWaterEntity::getMerId).eq(order.getMerId())
//                .ge(EbShopFlowingWaterEntity::getCreatedTime, startDate).le(EbShopFlowingWaterEntity::getCreatedTime, endDate);
//        List<EbDividendRecordEntity> dividendRecordCacheEntitys = new ArrayList<>();

//        for (Order order : orders) {
//            EbShopFlowingWaterEntity ebShopFlowingWaterEntity = new EbShopFlowingWaterEntity();
//            ebShopFlowingWaterEntity.setMerId(Long.valueOf(order.getMerId())).setCreatedTime(date).setBusinessLimit(order.getTotalPrice());
//
//            QueryWrapper where = QueryWrapper.create().from(EbShopFlowingWaterEntity.class).where(EbShopFlowingWaterEntity::getMerId).eq(order.getMerId())
//                    .ge(EbShopFlowingWaterEntity::getCreatedTime, startDate).le(EbShopFlowingWaterEntity::getCreatedTime, endDate);
//            // 店铺流水
//            long shopFlowingWaterCount = shopFlowingWaterService.count(where);
//
//            if (shopFlowingWaterCount > 2) {
//
//                EbShopFlowingWaterEntity shopFlowingWater = shopFlowingWaterService.getOne(where.orderBy(EbShopFlowingWaterEntity::getCreatedTime).desc().limit(1));
////                EbDividendConfigEntity dividendConfig = dividendConfigService.getOne(QueryWrapper.create().from(EbDividendConfigEntity.class)
////                        .where(EbDividendConfigEntity::getMerId).eq(order.getMerId())
////                        .orderBy(EbDividendConfigEntity::getCreatedTime).desc().limit(1));
//                // 增长比例
//                BigDecimal proportion = BigDecimal.valueOf(15);
//
//                BigDecimal increasePrice = shopFlowingWater.getBusinessLimit().divide(proportion
//                        .divide(BigDecimal.valueOf(100L), 2, RoundingMode.HALF_UP), 2, RoundingMode.HALF_UP);
//                // 当天
//                double theSameDay = orders.stream().parallel().map(Order::getTotalPrice).mapToDouble(BigDecimal::doubleValue).reduce(Double::sum).orElse(0D);
//
//                if (BigDecimal.valueOf(theSameDay).compareTo(increasePrice) > 0) {
//
//                    EbDividendRecordEntity ebDividendRecord = dividendRecordService.getOne(QueryWrapper.create().from(EbDividendRecordEntity.class)
//                            .where(EbDividendRecordEntity::getMerId).eq(order.getMerId()).orderBy(EbDividendRecordEntity::getCreatedTime).desc().limit(1));
//
//                    int numOfPeriods = ebDividendRecord.getNumOfPeriods();
//                    // 计算下一期
//                    EbDividendRecordEntity dividendRecordCacheEntity = new EbDividendRecordEntity();
//                    Dict dict = shopFlowingWaterService.priceCount(proportion.longValue(), numOfPeriods, BigDecimal.valueOf(200L), 36L);
//                    BeanUtil.copyProperties(dict, dividendRecordCacheEntity);
//                    dividendRecordCacheEntity.setCreatedTime(date).setMerId(order.getMerId()).setCreatedBy("admin")
//                            .setAmount(order.getTotalPrice()).setReleaseState(1);
//
//                    dividendRecordCacheEntitys.add(dividendRecordCacheEntity);
//                    shopFlowingWaterEntities.add(ebShopFlowingWaterEntity);
//                }
//            }
//
//        }
//        if (!dividendRecordCacheEntitys.isEmpty()) {
//            dividendRecordService.saveBatch(dividendRecordCacheEntitys);
//        }
        // 保存流水
//        if (!shopFlowingWaterEntities.isEmpty()) {
//            shopFlowingWaterService.saveBatch(shopFlowingWaterEntities);
//        }
    }

    /**
     * 获取一天的订单数据
     *
     * @return 指定时间订单数据
     */
    private Dict getOrderPriceList() {
        return getOrderPriceList(null, null);
    }

    /**
     * 获取订单列表
     *
     * @param data 订单原始数据
     * @return 订单操作数据
     */
    private List<Order> getOrderList(Dict data) {
        List<Map<String, Object>> countOrderPriceList = data.getBean("orderList");
        return countOrderPriceList.stream().parallel().map(it -> BeanUtil.copyProperties(it, Order.class)).toList();
    }

    /**
     * 获取一天的订单数据
     *
     * @return 指定时间订单数据
     */
    public Dict getOrderPriceList(LocalDateTime startDateTime, LocalDateTime endDateTime) {
        LocalDateTime date = LocalDateTime.now(), startTime = date.minusDays(1);

        LocalDateTime startDate = startDateTime == null ? DateUtil.toLocalDateTime(DateUtil.beginOfDay(DateUtil.date(startTime))) : startDateTime,
                endDate = endDateTime == null ? DateUtil.toLocalDateTime(DateUtil.beginOfDay(DateUtil.date(date
                        .withHour(23).withMinute(59).withSecond(59)))) : endDateTime;

        // TODO 商品积分总和(商户、用户)
        List<Map<String, Object>> countOrderPriceList = orderService.listMaps(Wrappers.<Order>query()
                .select("order_no as orderNo", "mer_id as merId").lambda()
                .ge(Order::getCreateTime, startDate)
                .le(Order::getCreateTime, endDateTime)
                .groupBy(Order::getMerId, Order::getOrderNo, Order::getMerId).orderByAsc(Order::getMerId));

        List<Map<String, Object>> merIdMapCountPrice = new ArrayList<>();

        // 根据按商户分类订单
        Map<Integer, List<Order>> collect = countOrderPriceList.stream().parallel().map(it -> BeanUtil.copyProperties(it, Order.class))
                .collect(Collectors.groupingBy(Order::getMerId));

        collect.forEach((k, v) -> {
            Map<String, Object> merIdMap = new HashMap<>();
            merIdMapCountPrice.add(MapUtil.builder(merIdMap).put("merId", k).put("total_price", countShopFlowingWater(v)).build());
        });

        return Dict.of().set("orderList", merIdMapCountPrice).set("startDate", startDate).set("endDate", endDate).set("date", date);
    }

    /**
     * 获取单个商户总积分流水
     *
     * @param orderList 商户订单列表
     * @return 订单总积分
     */
    public BigDecimal countShopFlowingWater(List<Order> orderList) {

        List<String> orderNoList = orderList.stream().parallel().map(Order::getOrderNo).collect(Collectors.toList());
        // 多线程list
        List<OrderDetail> orderDetailList = new CopyOnWriteArrayList<>();
        List<Product> productList = new CopyOnWriteArrayList<>();

        Lists.partition(orderNoList, SPLIT_SIZE).stream().parallel()
                .map(item -> orderDetailService.lambdaQuery().in(OrderDetail::getOrderNo, item).list())
                .peek(orderDetailList::addAll).toList();

        if (!orderDetailList.isEmpty()) {
            Lists.partition(orderDetailList.stream().parallel().map(OrderDetail::getProductId).collect(Collectors.toList()), SPLIT_SIZE)
                    .stream().parallel().map(item -> productService.lambdaQuery().in(Product::getId, item).list())
                    .peek(productList::addAll).toList();
            // TODO 秒杀商品(需额外处理)
            return productList.stream().parallel().map(Product::getPoints).reduce(BigDecimal.ZERO, BigDecimal::add);
        }
        return BigDecimal.ZERO;
    }


}
